package com.ijunfu.file.file.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.stream.IntStream;

/**
 *
 * @Title  : 
 * @Author : ijunfu <ijunfu@163.com>
 * @Date   : 2023/11/8 21:57
 * @Version: 1.0
 * @Motto  : 世界很大 世界很小
 *
 */
@Slf4j
public class FileHelper {


    static  byte[] buffer = new byte[1024*1024*5];
    static String SIZE = "5MB";

    static  {
        buffer[0] = '0';
        buffer[buffer.length - 1] = '1';
    }


    public static void genFile() throws InterruptedException {

        int processors = Runtime.getRuntime().availableProcessors();

        int limit = 100000;

        ThreadPoolExecutor executor = new ThreadPoolExecutor(processors + 1, processors * 2, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(limit));

        CountDownLatch latch = new CountDownLatch(limit);

        IntStream.range(0, limit).forEach(e->{
            executor.execute(()->{
                write(Thread.currentThread().getName() + "_" + e);
                latch.countDown();
            });
        });

        latch.await();

        executor.shutdown();
    }

    public static void copyFile() throws InterruptedException {

        int processors = Runtime.getRuntime().availableProcessors();

        int limit = 100000;

        ThreadPoolExecutor executor = new ThreadPoolExecutor(processors + 1, processors * 2, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(limit));

        CountDownLatch latch = new CountDownLatch(limit);

        IntStream.range(0, limit).forEach(e->{
            executor.execute(()->{
                copy(Thread.currentThread().getName() + "_" + e);
                latch.countDown();
            });
        });

        latch.await();

        executor.shutdown();
    }

    public static void copy(String flag) {

        log.info("writeFile start >>>");

        try {
            log.info("Will copy  data ...");

            File dir = new File("F:/", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH")));
            if(!dir.exists()) {
                dir.mkdirs();
            }

            final String FILE_NAME = flag + "_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")) + ".mp3";

            File f = new File(dir, FILE_NAME);
            if (f.exists()) {
                f.delete();
            }

            Files.copy(new File("G:/00.mp3").toPath(), f.toPath());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        log.info("copy file end <<<");
    }

    public static void write(String flag) {

        log.info("writeFile start >>>");
        RandomAccessFile file = null;
        try {
            log.info("Will write  data ...");

            File dir = new File("F:/", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH")));
            if(!dir.exists()) {
                dir.mkdirs();
            }

            final String FILE_NAME = flag + "_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")) + ".txt";

            File f = new File(dir, FILE_NAME);
            if (f.exists()) {
                f.delete();
            }
            file = new RandomAccessFile(f, "rw");
            file.write(buffer);
            log.info("write {} data", SIZE);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (file != null) {
                try {
                    file.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    file = null;
                }
            }
        }
        log.info("writeFile end <<<");
    }

    public static void writeFile(int N) {
        if (N < 1) {
            System.out.println("writeFile please input one integer greater than 0");
            return;
        }

        System.out.println("writeFile start >>>");
        RandomAccessFile file = null;
        try {
            System.out.println("Will write " + N + "GB data ...");
            String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
            final String FILE_NAME = "G:/" + N + "_" + timeStr + "GB.bin";
            File f = new File(FILE_NAME);
            if (f.exists()) {
                f.delete();
            }
            file = new RandomAccessFile(FILE_NAME, "rw");
            final int ONE_G_LENGTH = 1073741824; // 1G
            byte[] b = new byte[ONE_G_LENGTH]; // 1 GB
            b[0] = '0';
            b[b.length - 1] = '1';
            for (int i = 0; i < N; ++i) {
                file.write(b);
                file.seek(file.length());
                System.out.println("write " + (i + 1) + "GB data");
            }
            file.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (file != null) {
                try {
                    file.close();
                    file = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("writeFile end <<<");
    }

    public static void copyByPath(File srcFile, File targetFile) {

        System.out.println(srcFile.getName() + "\t\t" + targetFile.getName());

        Path srcPath = Paths.get(srcFile.toURI());
        Path targetPath = Paths.get(targetFile.toURI());

        try {
            Files.copy(srcPath, targetPath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void copy(File srcFile, File targetFile) {

        BufferedReader br = null;
        BufferedWriter bw = null;

        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile)));
            bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile)));

            int count=0;
            String line="";
            while((line=br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
                bw.flush();

                count++;

                if(count%Integer.MIN_VALUE==0) {
                    System.out.println("......");
                    count=0;
                }
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(Objects.nonNull(bw)) {
                try {
                    bw.close();
                } catch (IOException e) {
                    bw = null;
                }
            }

            if(Objects.nonNull(br)) {
                try {
                    br.close();
                } catch (IOException e) {
                    br=null;
                }
            }
        }

    }


    public static void copyByByte(File srcFile, File targetFile) {

        FileInputStream in = null;
        FilterOutputStream out = null;

        try {
            in = new FileInputStream(srcFile);

            out = new FilterOutputStream(new ByteArrayOutputStream(4096));
            byte[] buffer = new byte[4096];
            int len=0;
            int count = 0;
            while((len = in.read(buffer)) > -1) {
                out.write(buffer, 0, len);
                out.flush();
                count++;

                if(count%10000==0) {
                    System.out.print(".");
                }

                if(count%100000==0) {
                    System.out.println();
                    count=0;
                }
            }

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(Objects.nonNull(out)) {
                try {
                    out.close();
                } catch (IOException e) {
                    out = null;
                }
            }

            if(Objects.nonNull(in)) {
                try {
                    in.close();
                } catch (IOException e) {
                    in=null;
                }
            }
        }

    }
}
